package github.saw96x.remoting.handler;

import github.saw96x.common.exception.RpcException;
import github.saw96x.common.factory.SingletonFactory;
import github.saw96x.provider.Impl.ZkServiceProviderImpl;
import github.saw96x.provider.ServiceProvider;
import github.saw96x.remoting.pojo.RpcRequest;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Saw96x
 * @date 2022/3/18 8:23
 */
@Slf4j
public class RpcRequestHandler {
  private final ServiceProvider serviceProvider;

  public RpcRequestHandler() {
    serviceProvider = SingletonFactory.getInstance(ZkServiceProviderImpl.class);
  }

  /**
   * 调用对应的方法并返回
   */
  public Object handle(RpcRequest rpcRequest) {
    Object service = serviceProvider.getService(rpcRequest.getRpcServiceName());
    return invokeTargetMethod(rpcRequest, service);
  }

  /**
   * 获取方法执行结果
   *
   * @param rpcRequest 客户端请求
   * @param service    服务
   * @return 目标方法执行结果
   */
  private Object invokeTargetMethod(RpcRequest rpcRequest, Object service) {
    Object result;
    try {
      Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
      result = method.invoke(service, rpcRequest.getParameters());
      log.info("service:[{}] successful invoke method:[{}]", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
    } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
      throw new RpcException(e.getMessage(), e);
    }
    return result;
  }
}
